1 Modelagem e previsão

Para realizar a previsão da série do Ibovespa, começaremos com modelos mais simplificados, de modo que possamos estabelecer uma linha de base e, deste modo, avaliar se os modelos mais sofisticados realmente geram resultados melhores.

1.1 Médias-móveis do Ibovespa para 7, 15 e 30 dias

Médias-móveis são técnicas de suavização de séries temporais e, no máximo, permitem que seja realizada a previsão para o período imediatamente posterior.

Figure 1: Série temporal com dados observados e após eliminação de anomalias
Estatísticas das médias-móveis e da série original
date close rolling_avg_7d rolling_avg_15d rolling_avg_30d
Min. :2010-01-04 Min. : 37.50 Min. : 37.74 Min. : 38.12 Min. : 39.11
1st Qu.:2013-07-12 1st Qu.: 56.28 1st Qu.: 56.27 1st Qu.: 56.25 1st Qu.: 56.23
Median :2017-01-17 Median : 68.15 Median : 68.10 Median : 68.06 Median : 67.89
Mean :2017-01-17 Mean : 78.11 Mean : 78.11 Mean : 78.11 Mean : 78.11
3rd Qu.:2020-07-25 3rd Qu.:103.22 3rd Qu.:103.34 3rd Qu.:103.37 3rd Qu.:103.29
Max. :2024-01-31 Max. :133.89 Max. :133.00 Max. :132.78 Max. :132.06
Table 1: Estatísticas das médias-móveis e da série original.

Com o aumento da janela temporal, podemos verificar que houve uma redução no valor da mediana, assim como no valor máximo da série.

Medidas de acurácia da média-móvel para 7, 15 e 30 dias, previsão para 1 dia e respectivo MAPE
mae mape mase rmse fct fct_mape
rolling_avg_7d 0.4373373 0.5794936 0.8092715 0.5992426 128.0787 0.3131462
rolling_avg_15d 0.6743177 0.9039829 1.2477923 0.8792734 128.2599 0.1721072
rolling_avg_30d 0.9331605 1.2623652 1.7267685 1.1851084 127.9105 0.4440086
Table 2: Medidas de acurácia da média-móvel para 7, 15 e 30 dias, previsão para 1 dia e respectivo MAPE

Os resultados acima mostram que o modelo pode ser considerado acurado para realizar a previsão para o dia seguinte, pois a sua natureza não é de previsão, mas sim de suavização. Neste caso, o valor de fechamento do dia 01/02/2024 real foi de 128,481, e o MAPE foi calculado em relação a este valor.

1.2 Divisão entre teste e treino

O primeiro passo para o treinamento de modelos mais sofisticados é a divisão dos dados entre conjuntos de teste e treinamento. Neste caso, o conjunto de teste corresponderá a 20% do conjunto original.

Figure 2: Ibovespa fechamento - Conjuntos de Teste e Treino

1.3 Criação e ajuste de múltiplos modelos

Os modelos a seguir serão ajustados utilizando a biblioteca timetk. Esta biblioteca permite o ajuste de diversos modelos de séries temporais dentro de um framework coerente, criando uma camada de abstração em relação a várias outras bibliotecas tradicionais na modelagem de séries temporais, como a biblioteca forecast. A biblioteca também permite a integração com fluxos de trabalho de machine-learning como o H2O AutoML.

1.3.1 AUTO-ARIMA

A função arima_reg() é uma maneira de gerar uma especificação de um modelo ARIMA e retorna o melhor modelo de acordo com os valores AIC, AICc ou BIC. A função realiza uma busca pelos possíveis modelos dentro das restrições de ordem fornecidas.

Code
#|echo: false
#|warning: false
#|cache: true
#|code-fold: show

model_fit_arima_no_boost <- arima_reg(
        # ARIMA args
        seasonal_period = 253, #"auto" ,
        non_seasonal_ar = 5,
        non_seasonal_differences = 1,
        non_seasonal_ma = 1,
        seasonal_ar     = 5,
        seasonal_differences = 5,
        seasonal_ma     = 5,
) |> 
    set_engine(engine = "auto_arima") |> 
    fit(close ~ date, data = training(splits))

1.3.2 AUTO-ARIMA (Boost)

A função arima_boost() é uma forma de gerar a especificação de um modelo de séries temporais que utiliza boosting para aprimorar erros de modelagem (resíduos) em regressores exógenos. Ela funciona tanto com ARIMA “automatizado” (auto.arima), quanto com ARIMA padrão (arima). Os principais algoritmos são:

  • ARIMA Automatizado + Erros XGBoost (engine = auto_arima_xgboost, padrão)
  • ARIMA + Erros XGBoost (engine = arima_xgboost)

Iremos usar o auto_arima_xgboost para que o algoritmo escolha automaticamente os parâmetros que melhor ajustam o modelo.

Code
#|echo: false
#|warning: false
#|cache: true
#|code-fold: show


model_fit_arima_boost <- arima_boost(
    # ARIMA args
        mode = "regression",
        seasonal_period = "auto" ,
        non_seasonal_ar = 2,
        non_seasonal_differences = 2,
        non_seasonal_ma = 2,
        seasonal_ar     = 1,
        seasonal_differences = 1,
        seasonal_ma     = 1,
        

    # XGBoost Args
    trees = 10,
    tree_depth = 25, 
    learn_rate = 0.015,
    mtry = 1,
    sample_size = 0.5,
    stop_iter = 2) |> 
    set_engine(engine = "auto_arima_xgboost") |> 
    fit(close ~ date + as.numeric(date) 
        + factor(lubridate::month(date, label=T))
        + factor(lubridate::week(date)), 
        data = training(splits))
frequency = 7 observations per 1 week
Warning: `colsample_bynode = 1` with `counts = TRUE` will only sample a single column.
                            Set `counts = FALSE` to use a proportion (100% of columns).
Code
model_fit_arima_boost$fit$models$model_1$model
$phi
numeric(0)

$theta
numeric(0)

$Delta
[1] 1

$Z
[1] 1 1

$a
[1]  -0.727 105.747

$P
              [,1]          [,2]
[1,]  0.000000e+00 -7.420876e-23
[2,] -7.420876e-23  7.420876e-23

$T
     [,1] [,2]
[1,]    0    0
[2,]    1    1

$V
     [,1] [,2]
[1,]    1    0
[2,]    0    0

$h
[1] 0

$Pn
     [,1]         [,2]
[1,]    1 0.000000e+00
[2,]    0 7.420876e-23

1.3.3 Exponential Smoothing

Em seguida, crie um modelo Error-Trend-Season (ETS) usando um modelo state-space de suavização exponencial. Isso é feito com exp_smoothing().

Code
#|echo: false
#|warning: false
#|cache: true
#|code-fold: show

model_fit_ets <- exp_smoothing(trend = "additive", 
                               season = "auto", 
                               smooth_level = 0.3, 
                               smooth_trend = 0.15) |> 
    set_engine(engine = "ets")  |> 
    fit(close ~ date, data = training(splits))
frequency = 7 observations per 1 week

1.3.4 Prophet

O modelo seguinte é o Prophet utilizando prophet_reg(). Neste modelo foram inseridas informações sobre os lockdowns ocorridos em 2020 e 2021 no Estado de São Paulo. Vale ressaltar que os lockdowns foram bastante simplificados, tendo em vista que não foi possível homogeneizar as informações.

Code
#|echo: false
#|warning: false
#|cache: true
#|code-fold: show


lockdown1 <- tibble(holiday = 'lockdown',  
                    ds = as.Date(c('2020-02-21')),
                    lower_window = 0, 
                    upper_window = '2020-02-27') 

lockdown2 <- tibble(holiday = 'lockdown',  
                    ds = as.Date(c('2020-03-24')),
                    lower_window = 0, 
                    upper_window = '2021-08-16') 


lockdowns <- bind_rows(lockdown1, lockdown2)

model_fit_prophet <- prophet_reg(seasonality_weekly = T, 
                                 seasonality_daily = T,
                                 seasonality_yearly = "auto",
                                 prior_scale_seasonality = 45,
                                 prior_scale_changepoints = 0.6,
                                 changepoint_range = 0.9,
                                 changepoint_num = 35
                                 # modelar covid19
                                 ) |> 
    set_engine(engine = "prophet", holidays = lockdowns) |> 
    fit(close ~ date, data = training(splits))

1.3.5 Prophet (Boost)

Este modelo é do tipo Prophet utilizando prophet_boost(). É um modelo similar ao anterior, porém utiliza o boosting como uma forma de gerar a especificação de um modelo de séries temporais para aprimorar erros de modelagem (resíduos). Neste modelo não foram inseridas informações sobre os lockdowns.

Code
#|echo: false
#|warning: false
#|cache: true
#|code-fold: show

model_fit_prophet_boost <- prophet_boost(mode="regression",
                                         seasonality_weekly = T, 
                                 seasonality_daily = T,
                                 seasonality_yearly = "auto",
                                 prior_scale_seasonality = 45,
                                 prior_scale_changepoints = 0.65,
                                 changepoint_range = 0.9,
                                 changepoint_num = 35,
                                 # XGBoost Args
                                  trees = 10,
                                  tree_depth = 30, 
                                  learn_rate = 0.008,
                                  mtry = 1,
                                  sample_size = 0.5,
                                  stop_iter = 5,
                                 
                                   ) |> 
    set_engine(engine = "prophet_xgboost", counts = F) |> 
    fit(close ~ date + as.numeric(date) 
        + factor(lubridate::month(date, label=T))
        + factor(lubridate::week(date)), 
        data = training(splits))
    #fit(close ~ date , data = training(splits))

1.3.6 Regressão Linear (Parsip)

Podemos modelar uma regressão linear de série temporal (TSLM) usando o algoritmo linear_reg(). Os seguintes regressores derivados de date são usados:

  • Tendência: modelada usando as.numeric(date);
  • Sazonalidade: modelado usando month(date) e week(date).
Code
#|echo: false
#|warning: false
#|cache: true
#|code-fold: show

model_fit_lm <- linear_reg() |> 
    set_engine("lm") |> 
    fit(close ~ as.numeric(date)   
        + factor(lubridate::month(date, label=T), ordered = FALSE)
        + factor(lubridate::week(date)), 
        data = training(splits))

1.3.7 GLMNET

O modelo glmnet é um método de regressão que combina as técnicas de Lasso e Ridge para seleção de variáveis e regularização. Ele funciona através da minimização de uma função de custo que inclui o erro quadrático médio e um termo de penalização que controla a complexidade do modelo.

Abaixo é utilizado um fluxo de trabalho para padronizar o pré-processamento dos recursos fornecidos ao modelo de aprendizado de máquina.

# A tibble: 4,369 × 29
   date       close date_index.num date_year date_year.iso date_half
   <date>     <dbl>          <dbl>     <int>         <int>     <int>
 1 2010-01-04  70.0     1262563200      2010          2010         1
 2 2010-01-05  70.2     1262649600      2010          2010         1
 3 2010-01-06  70.7     1262736000      2010          2010         1
 4 2010-01-07  70.5     1262822400      2010          2010         1
 5 2010-01-08  70.3     1262908800      2010          2010         1
 6 2010-01-09  70.3     1262995200      2010          2010         1
 7 2010-01-10  70.4     1263081600      2010          2010         1
 8 2010-01-11  70.4     1263168000      2010          2010         1
 9 2010-01-12  70.1     1263254400      2010          2010         1
10 2010-01-13  70.4     1263340800      2010          2010         1
# ℹ 4,359 more rows
# ℹ 23 more variables: date_quarter <int>, date_month <int>,
#   date_month.xts <int>, date_month.lbl <ord>, date_day <int>,
#   date_hour <int>, date_minute <int>, date_second <int>, date_hour12 <int>,
#   date_am.pm <int>, date_wday <int>, date_wday.xts <int>,
#   date_wday.lbl <ord>, date_mday <int>, date_qday <int>, date_yday <int>,
#   date_mweek <int>, date_week <int>, date_week.iso <int>, date_week2 <int>, …
# A tibble: 4,369 × 65
   close date_index.num date_year date_half date_quarter date_month date_day
   <dbl>          <dbl>     <int>     <int>        <int>      <int>    <dbl>
 1  70.0          -1.73      2010         1            1          1   -1.33 
 2  70.2          -1.73      2010         1            1          1   -1.22 
 3  70.7          -1.73      2010         1            1          1   -1.10 
 4  70.5          -1.73      2010         1            1          1   -0.991
 5  70.3          -1.73      2010         1            1          1   -0.877
 6  70.3          -1.73      2010         1            1          1   -0.764
 7  70.4          -1.73      2010         1            1          1   -0.650
 8  70.4          -1.73      2010         1            1          1   -0.536
 9  70.1          -1.73      2010         1            1          1   -0.422
10  70.4          -1.72      2010         1            1          1   -0.309
# ℹ 4,359 more rows
# ℹ 58 more variables: date_second <int>, date_wday <dbl>, date_mday <int>,
#   date_qday <dbl>, date_yday <int>, date_mweek <int>, date_week <int>,
#   date_week2 <int>, date_week3 <int>, date_week4 <int>, date_mday7 <int>,
#   date_sin63.25_K1 <dbl>, date_cos63.25_K1 <dbl>, date_sin63.25_K2 <dbl>,
#   date_cos63.25_K2 <dbl>, date_sin63.25_K3 <dbl>, date_cos63.25_K3 <dbl>,
#   date_sin63.25_K4 <dbl>, date_cos63.25_K4 <dbl>, date_sin63.25_K5 <dbl>, …

1.4 Sumário dos modelos

A lista de modelos adotados está a seguir:

Code
models_tbl <- modeltime_table(
    model_fit_arima_no_boost,
    model_fit_arima_boost,
    model_fit_ets,
    model_fit_prophet,
    model_fit_prophet_boost,
    model_fit_lm,
    wflw_fit_glmnet

)

kable(tibble(Modelos = models_tbl$.model_desc), 
      caption = "List de modelos",) |> 
      kable_styling(full_width = FALSE, 
                position = "center") |> 
  column_spec(1, bold = TRUE) 
List de modelos
Modelos
ARIMA(0,1,0)
ARIMA(0,1,0) W/ XGBOOST ERRORS
ETS(M,AD,N)
PROPHET
PROPHET W/ XGBOOST ERRORS
LM
GLMNET
Table 3: Lista de modelos

1.5 Ajuste dos modelos aos dados de teste

Code
calibration_tbl <- models_tbl |> 
    modeltime_calibrate(new_data = testing(splits))


kable(tibble(Modelo = calibration_tbl$.model_desc,
             Tipo = calibration_tbl$.type), 
      caption = "Modelos e ajuste aos dados de treino") |> 
      kable_styling(full_width = FALSE, 
                position = "center") |> 
  column_spec(1, bold = TRUE) 
Modelos e ajuste aos dados de treino
Modelo Tipo
ARIMA(0,1,0) Test
ARIMA(0,1,0) W/ XGBOOST ERRORS Test
ETS(M,AD,N) Test
PROPHET Test
PROPHET W/ XGBOOST ERRORS Test
LM Test
GLMNET Test
Table 4: Tabela de modelos e ajuste aos dados de teste

1.6 Testando as previsões e avaliação de acurácia

1.6.1 Visualização das previsões em relação aos dados de teste

A Figure 3 permite comparar os diversos modelos aos dados de teste. Os modelos Prophet, Prophet Boost, LM e GLMNET são, aparentemente, aqueles que conseguem melhor captar o padrão sazonal e de tendência da série original. Os outros modelos apresentam um comportamento mais flat.

Figure 3: Previsões em relação aos dados de teste

1.6.2 Medição de acurácia das previsões em relação aos dados de teste

Na Table 5 podemos ver a acurácia dos modelos em relação aos dados de teste.

Métricas de acurácia - previsão x dados de teste
.model_id .model_desc .type mae mape mase smape rmse rsq
1 ARIMA(0,1,0) Test 8.55 7.27 12.31 7.67 10.84 NA
2 ARIMA(0,1,0) W/ XGBOOST ERRORS Test 8.26 7.03 11.90 7.40 10.54 0.01
3 ETS(M,AD,N) Test 9.15 7.78 13.17 8.24 11.46 0.01
4 PROPHET Test 10.93 10.10 15.74 9.45 12.75 0.04
5 PROPHET W/ XGBOOST ERRORS Test 10.70 9.89 15.41 9.25 12.58 0.01
6 LM Test 7.76 6.67 11.17 6.96 9.25 0.35
7 GLMNET Test 8.06 6.94 11.61 7.24 9.52 0.35
Table 5: Métricas de acurácia - previsão x dados de teste

Tomando o MAPE como métrica, podemos verificar que os modelos LM e GLMNET são os que apresentam menor erro. Chama a atenção o fato de que, apesar de não conseguirem captar os padrões de tendência e sazonalidade, os modelos ARIMA(com e sem boosting) e ETS conseguem apresentar um MAPE menor que dos modelos do tipo PROPHET.

1.6.3 Refit para o dataset completo e previsão fora-da-amostra

Uma vez satisfeitos com nosso conjunto de modelos, podemos aplicar modeltime_refit() no conjunto de dados completo e fazer previsões para fora da amostra, incluindo os intervalos de confiança.

Como o conjunto de dados disponível fora da amostra (conjuntos de teste e treino) é de 20 dias, este é o número de períodos adiante para os quais faremos as previsões. Estas previsões poderão então ser comparadas aos índices diários de fechamento efetivamente realizados.

Figure 4: Previsões para 20 dias fora da amostra

1.7 Modelo ensemble

Mostramos na seção anterior que temos diferentes modelos preditivos com diferentes features e abordagens. Neste caso, ao invés de avaliar separadamente cada modelo, poder ser interessante combiná-los em um único modelo.

A técnica de ensemble combina então as previsões de diferentes modelos para melhorar a acurácia. As duas técnicas mais comuns são: - Averaging (Média/Mediana): Combina as previsões de vários modelos, geralmente de forma simples, como a média ponderada. - Stacking (Empilhamento): Combina as previsões de vários modelos através de um meta-modelo. O meta-modelo aprende a combinar as previsões de forma mais complexa, levando em conta as correlações entre elas.

Abaixo aplicaremos a técnica da mediana do conjunto de modelos, uma vez que esta medida de tendência central é menos sensível à existência de outliers. Outro ponto é que escolhemos quatro modelos para o ensemble, com base no seu desempenho avaliado até então: Prophet, Prophet Boost, LM e GLMNET.

Modelos para ensemble
Modelos
PROPHET
PROPHET W/ XGBOOST ERRORS
LM
GLMNET
Table 6: Modelos para ensemble

O gráfico da Figure 5 mostra que o modelo aparentemente possui uma boa performance, inclusive ao captar os padrões de tendência e sazonalidade da série original.

Figure 5: Modelo ensemble - previsão x teste

A Table 7 mostra que o modelo ensemble, de fato, apresenta uma acurácia maior que a de qualquer dos modelos tomados individualmente.

Métricas de acurácia do modelo ensemble
.model_id .model_desc .type mae mape mase smape rmse rsq
1 ENSEMBLE (MEDIAN): 4 MODELS Test 5.7 5.15 8.2 5.05 7.41 0.16
Table 7: Métricas de acurácia do modelo ensemble

1.7.1 Refit para o dataset completo e previsão fora-da-amostra

A seguir fazemos o refit para o modelo ensemble, da mesma forma que foi feito para os modelos individualmente.

Figure 6: Previsões para 20 dias fora da amostra

Interessante notarmos que, ao contrário do ocorrido para os valores de teste, na previsão completamente fora do amostra inicial, o modelo não parece performar bem.

1.8 Modelos utilizando AutoML(H2O)

Todos os passos anteriormente descritos foram novamente aplicados, porém utilizando o H2O AUTOML.

O H2O AutoML para previsão é implementado via automl_reg(). Esta função treina e faz validação cruzada de vários modelos de aprendizado de máquina (XGBoost GBM, GLMs, Random Forest, GBMs…) e, em seguida, treina dois modelos Stacked Ensembled, um de todos os modelos e um dos melhores modelos de cada tipo . Finalmente, o melhor modelo é selecionado com base em uma métrica de parada.

Os melhores modelos estão na Table 8.

 Connection successful!

R is connected to the H2O cluster: 
    H2O cluster uptime:         1 hours 11 minutes 
    H2O cluster timezone:       America/Sao_Paulo 
    H2O data parsing timezone:  UTC 
    H2O cluster version:        3.44.0.3 
    H2O cluster version age:    2 months and 20 days 
    H2O cluster name:           H2O_started_from_R_carlo_ska449 
    H2O cluster total nodes:    1 
    H2O cluster total memory:   7.75 GB 
    H2O cluster total cores:    16 
    H2O cluster allowed cores:  6 
    H2O cluster healthy:        TRUE 
    H2O Connection ip:          localhost 
    H2O Connection port:        54321 
    H2O Connection proxy:       NA 
    H2O Internal Security:      FALSE 
    R Version:                  R version 4.3.3 (2024-02-29 ucrt) 

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |======================================================================| 100%

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |=========                                                             |  12%
  |                                                                            
  |========================                                              |  35%
  |                                                                            
  |========================================                              |  57%
  |                                                                            
  |=======================================================               |  79%
  |                                                                            
  |======================================================================| 100%

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |======================================================================| 100%
                        model_id        mae       rmse         mse      rmsle
1 GBM_4_AutoML_8_20240311_232242  0.5469351  0.7364108   0.5423009 0.01050650
2 DRF_1_AutoML_8_20240311_232242  0.5546981  0.8137777   0.6622341 0.01202878
3 GBM_3_AutoML_8_20240311_232242  0.5690212  0.7588869   0.5759093 0.01086789
4 GBM_2_AutoML_8_20240311_232242  0.5885765  0.7857932   0.6174710 0.01129913
5 GBM_1_AutoML_8_20240311_232242  0.7879059  1.0266900   1.0540924 0.01478201
6 GLM_1_AutoML_8_20240311_232242 12.7633542 15.0391229 226.1752168 0.22655136
  mean_residual_deviance
1              0.5423009
2              0.6622341
3              0.5759093
4              0.6174710
5              1.0540924
6            226.1752168

[6 rows x 6 columns] 
Melhores modelos segundo o AutoML
model_id mae rmse mse rmsle mean_residual_deviance
GBM_4_AutoML_8_20240311_232242 0.55 0.74 0.54 0.01 0.54
DRF_1_AutoML_8_20240311_232242 0.55 0.81 0.66 0.01 0.66
GBM_3_AutoML_8_20240311_232242 0.57 0.76 0.58 0.01 0.58
GBM_2_AutoML_8_20240311_232242 0.59 0.79 0.62 0.01 0.62
GBM_1_AutoML_8_20240311_232242 0.79 1.03 1.05 0.01 1.05
GLM_1_AutoML_8_20240311_232242 12.76 15.04 226.18 0.23 226.18
Table 8: Previsões para 20 dias fora da amostra

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |======================================================================| 100%

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |======================================================================| 100%
Métricas de acurácia do modelo AutoML
.model_id .model_desc .type mae mape mase smape rmse rsq
1 H2O AUTOML - GBM Test 7.8 6.9 11.23 6.94 9.92 0.07
Table 9: Métricas de acurácia do modelo AutoML

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |======================================================================| 100%

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |======================================================================| 100%
Figure 7: Modelo AutoML - previsão x teste

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |======================================================================| 100%

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |=========                                                             |  12%
  |                                                                            
  |========================                                              |  35%
  |                                                                            
  |========================================                              |  57%
  |                                                                            
  |========================================================              |  80%
  |                                                                            
  |======================================================================| 100%

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |======================================================================| 100%
                        model_id        mae       rmse         mse      rmsle
1 DRF_1_AutoML_9_20240311_232506  0.5872533  0.8125059   0.6601659 0.01058995
2 GBM_3_AutoML_9_20240311_232506  0.6129993  0.8162672   0.6662921 0.01088953
3 GBM_2_AutoML_9_20240311_232506  0.6376214  0.8437928   0.7119863 0.01127391
4 GBM_1_AutoML_9_20240311_232506  0.8433915  1.0877047   1.1831016 0.01450204
5 GLM_1_AutoML_9_20240311_232506 11.7284783 14.2006439 201.6582884 0.21667184
  mean_residual_deviance
1              0.6601659
2              0.6662921
3              0.7119863
4              1.1831016
5            201.6582884

[5 rows x 6 columns] 

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |======================================================================| 100%

  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |======================================================================| 100%
Figure 8: Previsões para 20 dias fora da amostra

1.8.1 Comparação entre previsto e real

Na Table 10 temos as métricas de acurácia para cada um dos modelos, comparando as previsões fora da amostra com os valores efetivamente observados de 01/02/2024 a 23/02/2024. Os valores são comparados estritamente com os dias em que o pregão ocorreu.

Surpreendentemente, o modelo ARIMA(0,1,0) W/ XGBOOST ERRORS é aquele com o menor MAPE. Por outro lado, os modelos do tipo PROPHET e ENSEMBLE parecem ser os mais equilibrados, pois possuem um MAPE pequeno, ao mesmo tempo em que sabemos a capacidade que eles possuem em captar os padrões de tendência e sazonalidade.

Métricas de acurácia - previsão (fora da amostra) x valores reais
Modelo MAE MAPE MASE SMAPE RMSE
ARIMA(0,1,0) W/ XGBOOST ERRORS 0.90 0.69 0.91 0.70 1.12
ARIMA(0,1,0) 1.02 0.79 1.04 0.80 1.32
ETS(M,AD,N) 1.14 0.88 1.16 0.89 1.45
PROPHET W/ XGBOOST ERRORS 1.93 1.50 1.96 1.51 2.22
PROPHET 2.53 1.96 2.57 1.98 2.75
ENSEMBLE (MEDIAN): 4 MODELS 3.63 2.82 3.68 2.86 3.78
GLMNET 4.72 3.67 4.80 3.74 4.84
LM 11.71 9.10 11.89 9.54 11.78
UPDATE: H2O AUTOML - DRF 12.65 9.83 12.85 10.35 12.79
Table 10: Métricas de acurácia - previsão x dados reais fora da amostra

2 Conclusões

  • Todos os modelos atendem o requisito estabelecido, ou seja, todos possuem acurácia maior que 70%;
  • Dos modelos